#include "stdafx.h"
#include "gfx.h"


void displayShape( int step, Shape* shape ) {

	vector<float*> outline = shape->getOutline();
	vector<float*> required = shape->getRequired();

	if (outline.size() >= 3) {
		float n[3] = {0, 0, 0};
		// assume each shape is made of at least 3 points
		normal(n, outline.at(0), outline.at(1), outline.at(2));
		glNormal3fv( n );
	}

	glLineWidth(5.0);

	vector<float*>::iterator it;

	float zCoords[2] = {-1.f,0.f};


	glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray );

	// loop once again to connect the vertices

	for( it = outline.begin(); it < outline.end(); it++ ) {
		glBegin( GL_LINES );
		float* coords = *it;
		glVertex3f( coords[0], coords[1], zCoords[1] );
		glVertex3f( coords[0], coords[1], zCoords[0] );
		glEnd();
	}

	float frontColor[4];

	// decide when to show a blue border
	bool isHit = HIT_TIME != 0;// && (CURR_TIME_MS/500 % 2 == 0);

	for (int i = 0; i < 4; i++ ) {
		frontColor[i] = isHit ? yellow[i] : white[i];
	}

	// loop twice for the 3d effect
	for (int i = 0; i < 2; i++) {
		glBegin( GL_LINE_LOOP );  
		for( it = outline.begin(); it < outline.end(); it++ ) {
			float* coords = *it;
			coords[2] = zCoords[i];
			glVertex3fv( coords );
		}
		glEnd();
		glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, frontColor );
		if (isHit) {
			glLineWidth(10.0);
		}
	}

	for( it = required.begin(); it < required.end(); it++ ) {
		float* r = *it;
		glPushMatrix();
		glTranslatef(r[0], r[1], 0.f);
		//drawCircle(REQUIRED_POINT_RADIUS, r[0], r[1]);
		glutSolidSphere(REQUIRED_POINT_RADIUS, 50, 50);
		glPopMatrix();
	}
	glNormal3f( 0.f, 0.f, 1.f );
}

void displayScore(int step, int score, int time) {

	glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);

	// show total score
	/*glRasterPos2f(-1.0, 0.92);
	printBitmapString("Lives:");
	glRasterPos2f(-.81f, 0.92);
	char s[10];
	sprintf(s, "%d", LIVES);
	printBitmapString(s);

		glRasterPos2f(-1.0, 0.85);
	printBitmapString("Score:");
	glRasterPos2f(-.81f, 0.85);
	sprintf(s, "%d", TOTAL_SCORE);
	printBitmapString(s);
	//printString(0.0f, 0.0f, "TESTING"); */

	// show countdown to next piece	

	glTranslatef(0.9, 0.85, 0);

	glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
	drawCircle(0.1, 0, 0);

	glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
	int timeLeft = SECONDS_PER_SHAPE - (time - PREV_TIME);
	if (timeLeft == SECONDS_PER_SHAPE) {
		drawCircle(0.1, 0, 0);
	}
	else {
		glRotatef(90, 0, 0, 1);
		for (int i = 0; i < timeLeft; i++) {
			drawWedge(0.1, 360/SECONDS_PER_SHAPE, 0, 0);	
			glRotatef(360/SECONDS_PER_SHAPE - 1, 0, 0, 1);
		}
	}
}

void showNewShape(bool hit) {
	if (MODE == CREATE) {
		return;
	}

	PREV_SHAPE = shapes.at(ACTIVE_SHAPE);
	
	// Choose shape according to level
	if(MONZY) {
		if (ACTIVE_SHAPE < 21) {
			ACTIVE_SHAPE = 21;
		} else {
			ACTIVE_SHAPE = (++ACTIVE_SHAPE) % shapes.size();
		}
	} else {
		if (TOTAL_SCORE >= 200) {
			ACTIVE_SHAPE = rand() % 7 + 14;
		}
		else if (TOTAL_SCORE >= 100) {
			ACTIVE_SHAPE = rand() % 7 + 7;
		}
		else {
			ACTIVE_SHAPE = rand() % 7;
		}
	}

	

	TOTAL_SCORE += 2*(SECONDS_PER_SHAPE - (CURR_TIME-PREV_TIME));
	SCORE += SECONDS_PER_SHAPE - (CURR_TIME-PREV_TIME);
	PREV_TIME = CURR_TIME;
	PREV_STEP = CURR_STEP;

	if (hit) {
		// Request text to be drawn		
		if (SCORE >= 100) {
			LIVES++;
			SCORE = 0;
			rasterTimer[DISPLAY_NEXTLEVEL] = CURR_TIME + 2;
		} else {
			rasterTimer[DISPLAY_CLEAR] = CURR_TIME + 2;
		}

		playSound("../../sounds/hit.wav");
	}
	else {
		--LIVES;
		playSound("../../sounds/miss.wav");
		if (LIVES <= 0) {
			rasterTimer[DISPLAY_GAMEOVER] = CURR_TIME + 10;
			SCREEN = GAMEOVER;
		}
		else {
			// Request text to be drawn
			rasterTimer[DISPLAY_NOT_CLEAR] = CURR_TIME + 2;
		}
	}
}

void displayBar(int step) {
		// draw gray bar
		glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
		glRectf(-1.0f, -1.0f, 1.0f, -0.95f);

		// draw white bar as percentage
		glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
		glRectf(-1.0f, -1.0f, (float)SCORE / 50.f - 1.f, -0.95f); 
}

void displaySilhoutte(int step) {
	// don't do anything during a transition phase
	if (PREV_SHAPE) {
		return;
	}

	int width = FRAME_WIDTH;
	int height = FRAME_HEIGHT;

	// size of each dot
	glPointSize(35.f);

	int activePoints = 0;
	int hitPoints = 0;
	set<float> hitRequiredPoints = set<float>();

	Shape* shape = shapes.at(ACTIVE_SHAPE);
	vector<float*> outline = shape->getOutline();
	vector<float*>::iterator it;
	vector<float*> required = shape->getRequired();
	float* xp = (float*) malloc(outline.size() * sizeof(float));
	float* yp = (float*) malloc(outline.size() * sizeof(float));

	for (int i = 0; i < height*width; i++) {
		if (FRAME_DATA[i] == '1') {
			int row = i%height;//= FRAME_DATA[i] - '0';
			int col = i/height;
			++activePoints;

			float x = (float)col/(float)(width-1) * 2.f - 1.f;
			float y = (float)row/(float)(height-1) * 2.f - 1.f;

			for (unsigned int k = 0; k < outline.size(); k++) {
				float* coordinates = outline.at(k);
				xp[k] = coordinates[0];
				yp[k] = coordinates[1];
			}



			bool isHittingRequiredPoint = false;			

			// check point against required points

			for( it = required.begin(); it < required.end(); it++ ) {

				float* coord = *it;
				float rx = coord[0];
				float ry = coord[1];

				glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow);
				if (sqrt(pow(rx-x, 2)+pow(ry-y,2)) < REQUIRED_POINT_RADIUS*3.f) {
					hitRequiredPoints.insert(rx);
					hitRequiredPoints.insert(ry);

					//drawCircle(REQUIRED_POINT_RADIUS, rx, ry);
					glPushMatrix();
					glTranslatef(rx, ry, 0.f);
					float s = sin((float)CURR_TIME_MS/500.f);
					glutSolidSphere(REQUIRED_POINT_RADIUS+(s*s/50.f), 50, 50);
					glPopMatrix();

					// hack: don't show a point inside the radius of a required point back so that it doesn't draw on top of the sphere
					//isHittingRequiredPoint = true;
				}
				glNormal3f( 0.f, 0.f, 1.f );
			}

			if (!isHittingRequiredPoint) {
				if (!pnpoly(outline.size(), xp, yp, x, y)) {
					glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
				}
				else {
					++hitPoints;
					glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
				}
				drawCircle(0.025f, x, y);
			}
		}
	}

	if (activePoints == 0) {
		// scene is empty
		return;
	}

	HIT_PERCENTAGE = 100 * hitPoints / activePoints;

	// check to see if all the points are within the active shape's bounds	
	//printf("%d %d %d\n", HIT_PERCENTAGE, hitRequiredPoints.size(), required.size());
	if (HIT_PERCENTAGE > 70 && hitRequiredPoints.size()/2 == required.size()) {
		if (WITHIN_COUNTER < 5) {
			WITHIN_COUNTER++;
		}
		if (HIT_TIME == 0) {
			HIT_TIME = CURR_TIME;
		}
		// it takes three seconds to "hit"
		else if (CURR_TIME - HIT_TIME > 1) {
			showNewShape(true);
			WITHIN_COUNTER = 0;
			HIT_TIME = 0;
		}
	}
	else {
		WITHIN_COUNTER--;
		if (WITHIN_COUNTER <= 0) {
			HIT_TIME = 0;
		}
	}

}

